import java.io.*;
import java.net.*;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;

import org.bouncycastle.openssl.PEMReader;
import org.bouncycastle.openssl.PasswordFinder;
import org.bouncycastle.util.encoders.Base64;
import java.io.FileInputStream;
import java.security.Key;
import java.security.NoSuchAlgorithmException;

import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.util.encoders.Hex;
import javax.crypto.Mac;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Arrays;

public class Client{

	/*In Run-configuration eintragen:
	 * args[0] = localhost
	 * args[1] = 10630
	 * args[2] = 10631
	 * args[3] = keys/auction-server.pub.pem
	 * args[4] = keys/
	 * */

	private static String serverPublicKeyPath;
	private static String clientKeyDirPath;




	public static void main(String args[]) throws Exception{


		//InputStream zum auslesn des safety-keys
		FileInputStream fis;
		//wird zum auslesen des security-keys benoetigt:
		byte[] keyBytes = null;
		byte[] input = null;
		Key secretKey= null;
		Mac hMac=null;
		boolean askAgain=false;
		boolean authSucc = false;
		boolean handsFin = false;
		SecretKey aesKey = null;
		IvParameterSpec iVector = null;
		String serverChallenge;
		String userName="";
		PrivateKey privK = null;
		String onlineClients="";
		Boolean fileErr = false;


		try{			

			if(args.length==5){
				if(checkParameter(args[0],args[1],args[2])){

					String sentence="";
					String modifiedSentence="";
					String userTemp="";
					String cPort = args[2]; 

					//Erzeugt Input Stream
					BufferedReader inFromUser= new BufferedReader(new InputStreamReader(System.in));

					//Erzeugt client Socket, verbunden mit dem Server
					Socket clientSocket= new Socket(args[0],Integer.parseInt(args[1]));

					//Erzeugt output stream, attached to Socket
					DataOutputStream outToServer= new DataOutputStream(clientSocket.getOutputStream());

					//Erzeugt Input stream, attached to Socket
					BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

					//Eincryption-Paths werden ausgelesen
					serverPublicKeyPath = args[3];
					clientKeyDirPath = args[4];
					//While-schleife ermoeglicht eingeben mehrerer Befehle
					end:
						while(true){

							//Falls ein mismatch bei der Hmac dingens vorliegt, wird nochmals angefragt (sentence bleibt gleich) daraufhin wird "askAgain" sofort wieder auf false gesetzt

							if(askAgain==false){
								System.out.print(userName + ">");
								sentence = inFromUser.readLine();
							}
							else
								sentence="!sendAgain";

							try{

								if(!userName.equals("")){
									//outToServer.writeBytes(sentence+'\n');
									outToServer.writeBytes(aesB64SCypher("ENCRYPT_MODE", aesKey, iVector, sentence) + '\n');
									if(sentence.equals("!end")){
										break;
									}
									modifiedSentence = inFromServer.readLine();
									modifiedSentence = aesB64SCypher("DECRYPT_MODE", aesKey, iVector,modifiedSentence);

								}else if(sentence.equals("!list")){

									// !list-Befehl zum Server senden
									outToServer.writeBytes(sentence + '\n');
									//read Line from Server
									modifiedSentence = inFromServer.readLine();
									//System.out.println("check"+modifiedSentence);

								}else if(sentence.equals("!end")){

									//!end-Befehl zum Server senden
									outToServer.writeBytes(sentence + '\n');
									break;

								}else if(sentence.length()>=6 && sentence.substring(0,6).equals("!login")){
									userTemp = sentence.substring(7,sentence.length());

									////////////////////////////////////////////////////////////////////////Authentification-Handshake////////////////////////////////////////////////////////////////////////
									//System.out.println(modifiedSentence);
									//Generieren der Client-Challenge
									SecureRandom secureRandom = new SecureRandom(); 
									final byte[] clientChallenge = new byte[32]; 
									secureRandom.nextBytes(clientChallenge);
									//clientChallenge mit Base64 encoden
									String cChallengeB64 = new String(Base64.encode(clientChallenge));

									//clientbefehl + TCP-Port + Client-Challenge
									sentence = sentence +" "+ cPort +" "+ cChallengeB64;

									//ServerPubKey auslesen
									PublicKey publicKey = getPublicKey(serverPublicKeyPath);
									if(publicKey==null){
										System.out.println("ERROR:No KeyPair Found");
										authSucc = false;
									}else{
										//Senden an Server + RSABase64 verschluesselung
										outToServer.writeBytes(rsaB64Cipher("ENCRYPT_MODE", publicKey, sentence)+'\n');

										//Message 2 von Server
										modifiedSentence = inFromServer.readLine();

										if(modifiedSentence.length()>=5 && modifiedSentence.substring(0, 5).equals("ERROR")){
											System.out.println(modifiedSentence);
											userName = "";
										}else{
											//Decoding/decrypting von Message2:
											clientKeyDirPath = args[4];


											privK = getPrivateKey(clientKeyDirPath+userTemp+".pem", inFromUser);

											if(privK.equals(null)){
												System.out.println("ERROR:No KeyPair Found");
												authSucc = false;
												fileErr = false;
											}else{
												modifiedSentence = rsaB64Cipher("DECRYPT_MODE", privK, modifiedSentence);
												//Gestartet wird nach "!ok "
												int sp1 = getNextSpace(modifiedSentence,4,modifiedSentence.length()); 			//bis hier Client Challenge  iV
												int sp2 = getNextSpace(modifiedSentence,sp1+1,modifiedSentence.length()); 		//bis hier Server Challenge
												int sp3 = getNextSpace(modifiedSentence,sp2+1,modifiedSentence.length());		//bis hier AES key, ab hier Initialvektor
												byte[] sClientChallenge = Base64.decode(modifiedSentence.substring(4,sp1));

												if(MessageDigest.isEqual(clientChallenge, sClientChallenge)){

													serverChallenge = modifiedSentence.substring(sp1+1,sp2);
													byte[] aesKeyByte =  Base64.decode(modifiedSentence.substring(sp2+1,sp3));
													aesKey = new SecretKeySpec(aesKeyByte,"AES");
													//System.out.println(Arrays.toString(aesKeyByte));
													String iVS = modifiedSentence.substring(sp3+1,modifiedSentence.length());
													//System.out.println(iVS.length());
													byte[] iVB = Base64.decode(iVS);
													iVector = new IvParameterSpec(iVB);
													outToServer.writeBytes(aesB64SCypher("ENCRYPT_MODE", aesKey, iVector, serverChallenge)+'\n');
													//outToServer.writeBytes(serverChallenge+'\n');
													authSucc = true;
													modifiedSentence = inFromServer.readLine();
													modifiedSentence = aesB64SCypher("DECRYPT_MODE", aesKey, iVector,modifiedSentence);
												}else{

													System.err.println("Authentification ERROR: Wrong Server");
												}

											}
										}
									}

								}else System.out.println("Invalid Command, usage limited to <!login>, <!list> and <!end>");
								///////////////////////////////////////////////////////^^^^^^^^^^^^^^^^^^^^Authentification-Handshake^^^^^^^^^^^^^^^^^^^^////////////////////////////////////////////////////

							}
							catch(IOException ex){

								System.out.println("The server is offline. The commands '!bid <auction-ID> <bid>' and '!end' can be used.");
								authSucc = false;
								//ex.printStackTrace();
								//Versucht zu reconnecten 

								//Versucht zu reconnecten und ermoeglicht die Eingabe der Befehle "!end" und "!bid [...]"
								serverDown:
									while(true){
										while(true){
											long startTime=System.currentTimeMillis();

											System.out.print(userName + ">");
											sentence=inFromUser.readLine();

											if(sentence.length()>=4 && sentence.substring(0,4).equals("!end"))
												break end;
											else if(sentence.length()>=4 && sentence.substring(0,4).equals("!bid")){

												try{
													int space= 0;

													for(int n=5; n<sentence.length(); n++){
														if(sentence.charAt(n)==' '){
															space=n;
															break;
														}
													}

													//liest die ID der auf zu bietenden Auktion aus
													int id=Integer.parseInt(sentence.substring(5, space));

													//liest den zu bietenden Betrag auf die Auktion aus
													double bid=Double.parseDouble(sentence.substring(space+1, sentence.length()));

													System.out.println(id + " "+bid);

													//onlineClients in Arraylist umwandeln
													ArrayList<String> onlineClientList= new ArrayList<String>();
													space=0;
													String addString="";

													for(int n=0; n<onlineClients.length();n++){
														if(onlineClients.charAt(n)=='|'){
															addString=onlineClients.substring(space, n);
															onlineClientList.add(addString);
															space=n+1;
														}
														else if(n==onlineClients.length()-1){
															onlineClientList.add(onlineClients.substring(space, onlineClients.length()));
														}
													}

													//zwei rnd clients auswaehlen wo user eingeloggt ist
													//zaehlt alle nicht eingeloggten Clients
													int counter=0;
													for(int n=0; n<onlineClientList.size();n++){
														if(onlineClientList.get(n).substring(onlineClientList.get(n).length()-13, onlineClientList.get(n).length()).equals("not logged in")){
															counter++;
														}
													}

													//Falls es weniger als zwei eingeloggte User gibt, wird der '!bid' Vorgang hier abgebrochen
													if((onlineClientList.size()-counter)>=2){

														ArrayList <String> messageThem=new ArrayList<String>();

														while(counter!=2){
															int n= (int)(Math.round(Math.random()*onlineClientList.size())-1);

															if(!onlineClientList.get(n).substring(onlineClientList.get(n).length()-13, onlineClientList.get(n).length()).equals("not logged in") && !messageThem.contains(onlineClientList.get(n))){
																messageThem.add(onlineClientList.get(n));
															}
														}

														System.out.println(messageThem.toString());
													}
													else{
														System.out.println(onlineClientList.toString());
														System.out.println("There are not enough user online for verification.");
													}


													//!getTimestamp zu zwei rnd clients schicken(socket implementieren etc)
													//!timestamp der clients auslesen (signatur!)
													//mittelwert des timestamps auslesen
													//erhaltene informationen in !signedbid umwandeln
													//server erhaelt signedbid, muss timestamps verifizieren
													//ueberpruefen ob timestamp vor ablauf der auktion ist
												}
												catch(StringIndexOutOfBoundsException se){
													System.out.println("Usage: !bid <auction-ID> <bid>");
													se.printStackTrace();
												}

											}
											else
												System.out.println("Invalid command");

											//nach 5 sekunden wird die Schleife verlassen, um danach einen reconnect zu versuchen
											if((System.currentTimeMillis()-startTime)>=5000)
												break;
										}

										try {

											clientSocket= new Socket(args[0],Integer.parseInt(args[1]));
											outToServer= new DataOutputStream(clientSocket.getOutputStream());
											inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));									
											//////////////////////////////////////////////////////////////////RELOGIN//////////////////////////////////////////////////////////////////
											//////////////////////////Authentification-Handshake/////////////////////////////////
											//System.out.println(modifiedSentence);
											//Generieren der Client-Challenge
											SecureRandom secureRandom = new SecureRandom(); 
											final byte[] clientChallenge = new byte[32]; 
											secureRandom.nextBytes(clientChallenge);
											//clientChallenge mit Base64 encoden
											String cChallengeB64 = new String(Base64.encode(clientChallenge));

											//clientbefehl + TCP-Port + Client-Challenge
											sentence = "!login "+userName+" "+ cPort +" "+ cChallengeB64;

											//ServerPubKey auslesen
											PublicKey publicKey = getPublicKey(serverPublicKeyPath);

											if(publicKey==null){
												System.out.println("ERROR:No KeyPair Found");
												authSucc = false;
											}else{
												//Senden an Server + RSABase64 verschluesselung
												outToServer.writeBytes(rsaB64Cipher("ENCRYPT_MODE", publicKey, sentence)+'\n');

												//Message 2 von Server
												modifiedSentence = inFromServer.readLine();

												if(modifiedSentence.length()>=5 && modifiedSentence.substring(0, 5).equals("ERROR")){
													System.out.println(modifiedSentence);
													userName = "";
												}else{
													//Decoding/decrypting von Message2:
													//System.out.println(modifiedSentence);
													clientKeyDirPath = args[4];

													modifiedSentence = rsaB64Cipher("DECRYPT_MODE", privK, modifiedSentence);
													//Gestartet wird nach "!ok "
													int sp1 = getNextSpace(modifiedSentence,4,modifiedSentence.length()); 			//bis hier Client Challenge  iV
													int sp2 = getNextSpace(modifiedSentence,sp1+1,modifiedSentence.length()); 		//bis hier Server Challenge
													int sp3 = getNextSpace(modifiedSentence,sp2+1,modifiedSentence.length());		//bis hier AES key, ab hier Initialvektor
													byte[] sClientChallenge = Base64.decode(modifiedSentence.substring(4,sp1));

													if(MessageDigest.isEqual(clientChallenge, sClientChallenge)){

														serverChallenge = modifiedSentence.substring(sp1+1,sp2);
														byte[] aesKeyByte =  Base64.decode(modifiedSentence.substring(sp2+1,sp3));
														aesKey = new SecretKeySpec(aesKeyByte,"AES");
														//System.out.println(Arrays.toString(aesKeyByte));
														String iVS = modifiedSentence.substring(sp3+1,modifiedSentence.length());
														//System.out.println(iVS.length());
														byte[] iVB = Base64.decode(iVS);
														iVector = new IvParameterSpec(iVB);
														outToServer.writeBytes(aesB64SCypher("ENCRYPT_MODE", aesKey, iVector, serverChallenge)+'\n');
														//outToServer.writeBytes(serverChallenge+'\n');
														authSucc = true;
														modifiedSentence = inFromServer.readLine();
														modifiedSentence = aesB64SCypher("DECRYPT_MODE", aesKey, iVector,modifiedSentence);
													}else{

														System.err.println("Authentification ERROR: Wrong Server");
													}
												}
												//diese zwei readLine-Abfragen dienen dazu das nach dem reconnect nicht "You successfully logged in as <username>" angezeigt wird:
												//enthaelt "You successfully logged in as <username>", soll zwecks Formatierung/ Schoenheit nicht angezeigt werden
												modifiedSentence = inFromServer.readLine();
												modifiedSentence = aesB64SCypher("DECRYPT_MODE", aesKey, iVector,modifiedSentence);

												//enthaelt "STOP", wird in modifiedSentence gelassen da somit keine Ausgabe in stdout geschieht 
												modifiedSentence = inFromServer.readLine();	
												modifiedSentence = aesB64SCypher("DECRYPT_MODE", aesKey, iVector,modifiedSentence);


												System.out.println("The server is back online. All commands can be used.");
												break serverDown;

											}
										}
										catch(IOException io){

										}
									}
							}

							//Der Socket ist geclosed. Somit ist kein input vom Server mehr moeglich.					
							if (modifiedSentence==null) {
								System.out.println("No response from server");
								break;
							}

							//while Schleife ermoeglicht ausgeben mehrerer Serverantworten, bis der Server "STOP" sendet
							while(true){


								if(!authSucc){			
									break;

								}else if(modifiedSentence.equals("STOP")){			
									break;
								}else if(modifiedSentence.length()>=4 && modifiedSentence.substring(0, 4).equals("USER")){
									if(modifiedSentence.length()>4){

										userName= modifiedSentence.substring(5,modifiedSentence.length());

										keyBytes=new byte[1024];
										//der Pfad zum secret-key wird aktualisiert
										clientKeyDirPath= args[4]+userName+".key";

										//auslesen des Keys des momentanen Clients
										fis = new FileInputStream(clientKeyDirPath);
										fis.read(keyBytes);
										fis.close();
										input=Hex.decode(keyBytes);
										secretKey = new SecretKeySpec(input, "HmacSHA256");
										hMac = Mac.getInstance("HmacSHA256"); 
										hMac.init(secretKey);


									}else{
										userName="";
										authSucc = false;
									}
								}
								else{

									//entschluesselung der message
									if(!userName.equals("")){

										if(modifiedSentence.length()>=16 && modifiedSentence.substring(0,16).equals("onlineClientList")){
											onlineClients= modifiedSentence.substring(16,modifiedSentence.length());
										}
										else{
											int position=modifiedSentence.length()-44;	

											//erhaltene Hmac
											String receivedHash=modifiedSentence.substring(position, modifiedSentence.length());
											//erhaltener Plaintext
											modifiedSentence=modifiedSentence.substring(0,position);							
											//verschluesselung des Plaintexts
											hMac.update((modifiedSentence).getBytes());
											byte[] selfEncryptedMessage = hMac.doFinal();

											//b64.decryption
											byte [] encryptedMessage = Base64.decode(receivedHash);
											//liest die onlineClientsList aus (bei !login, !logout mituebergeben)

											modifiedSentence=modifiedSentence.replace('|', '\n');

											//Vergleich des verschluesselten Plaintextes (==selfEncryptedMessage) mit der encryptedMessage
											//Falls mismatch, wird erneut um den String angefragt (askAgain=true).
											if(!MessageDigest.isEqual(selfEncryptedMessage, encryptedMessage) && askAgain==false)
												askAgain = true;
											//modfiedSentence wurde bereits einmal ausgegeben. Erneute Ausgabe, danach wird nicht noch einmal nachgefragt
											else
												askAgain=false;

											System.out.println(modifiedSentence);
										}
									}
									//Ausgaben wenn kein User eingeloggt ist
									else{
										modifiedSentence=modifiedSentence.replace('|', '\n');
										if(modifiedSentence.substring(0,26).equals("Successfully logged out as") && modifiedSentence.length()>60){
											System.out.println(modifiedSentence.substring(0,modifiedSentence.length()-44));
											askAgain=false;
										}
										else{
											System.out.println(modifiedSentence);
										}
									}

								}
								modifiedSentence = inFromServer.readLine();
								modifiedSentence = aesB64SCypher("DECRYPT_MODE", aesKey, iVector,modifiedSentence);
							}
						}
					//Socket, Bufferedreader werden geschlossen.
					clientSocket.close();
					inFromUser.close();
					outToServer.close();
				}
				else{
					System.out.println("Usage: TCPClient <Hostname> <TCPPort> <ClientPort> <PublicServerKeyPath> <ClientKeyDirectoryPath>");
				}
			}
			else{
				System.out.println("Usage: TCPClient <Hostname> <TCPPort> <ClientPort> <PublicServerKeyPath> <ClientKeyDirectoryPath>");
			}
		}
		catch(ConnectException ce){
			System.out.println("Server konnte nicht erreicht werden. Der Server ist offline.");
		}
		catch(IOException ioe){

			ioe.printStackTrace();
		}
		catch(NoSuchAlgorithmException nsae){
			nsae.printStackTrace();
		}
		catch(InvalidKeyException ike){
			System.out.println("Das <username>.key file beinhaltet einen ungueltigen Key.");
		}

	}

	private static boolean checkParameter(String a, String b, String c){
		try{
			Integer.parseInt(b);
			Integer.parseInt(c);
			return true;
		}
		catch(NumberFormatException ex){
			return false;
		}
	}
	/**
	 * @param cyphermode
	 * @param key
	 * @param sentence
	 * @return sentence wird je nach Mode mit RSA und Base64 verschluesselt oderentschluesselt
	 */
	private static String rsaB64Cipher(String cyphermode, Key key, String sentence){
		try{
			if(cyphermode.equals("ENCRYPT_MODE")){
				Cipher crypt = Cipher.getInstance("RSA/NONE/OAEPWithSHA256AndMGF1Padding"); 
				crypt.init(Cipher.ENCRYPT_MODE, key);
				byte[] encrypt = crypt.doFinal(sentence.getBytes());
				return new String(Base64.encode(encrypt));	

			}else {
				byte[] dByte = Base64.decode(sentence);
				//System.out.println(new String(dByte));
				Cipher crypt = Cipher.getInstance("RSA/NONE/OAEPWithSHA256AndMGF1Padding"); 
				crypt.init(Cipher.DECRYPT_MODE, key);
				byte[] decrypt = crypt.doFinal(dByte);
				return new String(decrypt);	
			}
		}catch (IllegalBlockSizeException e) {
			System.err.println("RSA encryption/decryption error");
			e.printStackTrace();
		} catch (BadPaddingException e) {
			System.err.println("RSA encryption/decryption error");
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			System.err.println("RSA encryption/decryption error");
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			System.err.println("RSA Key error");
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			System.err.println("RSA encryption/decryption error");
			e.printStackTrace();
		}
		return "RSA encryption/decryption error";

	}

	/**
	 * @param cyphermode
	 * @param key
	 * @param iV
	 * @param sentence
	 * @return sentence wird je nach Mode mit AES und Base64 verschluesselt oder entschluesselt
	 */
	private static String aesB64SCypher(String cyphermode, Key key, IvParameterSpec iV, String sentence){

		try{
			if(cyphermode.equals("ENCRYPT_MODE")){
				Cipher crypt = Cipher.getInstance("AES/CTR/NoPadding"); 
				crypt.init(Cipher.ENCRYPT_MODE, key, iV);
				byte[] encrypt = crypt.doFinal(sentence.getBytes());
				return new String(Base64.encode(encrypt));	

			}else {
				byte[] dByte = Base64.decode(sentence.getBytes());
				Cipher crypt = Cipher.getInstance("AES/CTR/NoPadding"); 
				crypt.init(Cipher.DECRYPT_MODE, key, iV);
				byte[] decrypt = crypt.doFinal(dByte);
				return new String(decrypt);	
			}
		}catch (IllegalBlockSizeException e) {
			System.err.println("AES encryption/decryption error");
			e.printStackTrace();
		} catch (BadPaddingException e) {
			System.err.println("AES encryption/decryption error");
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			System.err.println("AES encryption/decryption error");
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			System.err.println("AES Key error");
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			System.err.println("AES encryption/decryption error");
			e.printStackTrace();
		} catch (InvalidAlgorithmParameterException e) {
			System.err.println("AES iVParameter error");
			e.printStackTrace();
		}
		return "AES encryption/decryption error";

	}
	/**
	 * @param keyPath
	 * @return Private Key wird aus file ausgelesen.
	 */
	private static PrivateKey getPrivateKey(String keyPath, BufferedReader userIn)throws FileNotFoundException{

		KeyPair keyPair = new KeyPair(null, null);
		final BufferedReader pwR = userIn; 
		try{
			PEMReader reader = new PEMReader(new FileReader(keyPath), new PasswordFinder(){
				public char[] getPassword() {

					// reads the password from standard input for decrypting the private key
					System.out.println("Enter pass phrase:");

					String pwInput = ""; 

					try{
						pwInput = pwR.readLine();

					} catch (IOException e) {
						System.err.println("ERROR: wrong userinput.");
						//e.printStackTrace();
					}

					return pwInput.toCharArray();
					//System.out.println("PW eingegeben!");
					//return "12345".toCharArray();
				}});

			keyPair = (KeyPair) reader.readObject();
			reader.close();
		} catch (FileNotFoundException e) {
			//System.out.println("fileNotFound");
			//e.printStackTrace();
			return null;
		} catch (IOException e) {
			System.out.println("Wrong Passphrase");
			//e.printStackTrace();
		}
		return keyPair.getPrivate();
	}
	/**
	 * @param keyPath
	 * @return Public Key wird aus file ausgelesen.
	 */
	private static PublicKey getPublicKey(String keyPath)throws FileNotFoundException{

		PEMReader in = null;
		PublicKey publicKey = null;
		try {
			in = new PEMReader(new FileReader(keyPath));
			publicKey = (PublicKey) in.readObject();
			in.close();
		} catch (FileNotFoundException e) {
			//System.out.println("fileNotFound");
			publicKey = null;
			//e.printStackTrace();
		} catch (IOException e) {

			e.printStackTrace();
		}
		return publicKey;
	}

	//gibt die Stelle im String zurueck, an der sich das naechste Leerzeichen befindet
	private static int getNextSpace(String input, int begin, int end){

		for(int n=begin; n<end; n++){
			if(input.charAt(n)==' '){
				end=n;
				break;
			}
		}
		return end;
	}


}
